#include <gst/gst.h>
#include <iostream>

int main(int argc, char* argv[])
{
    GstElement *pipeline, *source, *filter, *convert, *encoder, *payloader, *sink;
    GstBus* bus;
    GstMessage* msg;

    /* 初始化 GStreamer */
    gst_init(&argc, &argv);

    /* 创建管道 */
    pipeline = gst_pipeline_new("video-sender");

    /* 创建元素 */
    source = gst_element_factory_make("v4l2src", "source");
    filter = gst_element_factory_make("capsfilter", "filter");
    convert = gst_element_factory_make("videoconvert", "convert");
    encoder = gst_element_factory_make("x264enc", "encoder");
    payloader = gst_element_factory_make("rtph264pay", "payloader");
    sink = gst_element_factory_make("udpsink", "sink");

    /* 设置属性 */
    g_object_set(G_OBJECT(source), "device", "/dev/video0", NULL);
    g_object_set(G_OBJECT(encoder), "tune", 0, "bitrate", 500, "speed-preset", 6, NULL); // 6 for veryfast
    g_object_set(G_OBJECT(payloader), "config-interval", 1, "pt", 96, NULL);
    g_object_set(G_OBJECT(sink), "host", "127.0.0.1", "port", 5000, NULL);

    /* 创建一个 capsfilter 来设置捕获的格式和分辨率 */
    GstCaps* caps = gst_caps_new_simple("video/x-raw",
        "format", G_TYPE_STRING, "YUY2",
        "width", G_TYPE_INT, 256,
        "height", G_TYPE_INT, 384,
        "framerate", GST_TYPE_FRACTION, 25, 1,
        NULL);
    g_object_set(filter, "caps", caps, NULL);
    gst_caps_unref(caps);

    /* 检查元素是否都创建成功 */
    if (!pipeline || !source || !filter || !convert || !encoder || !payloader || !sink) {
        g_printerr("Not all elements could be created.\n");
        return -1;
    }

    /* 添加到管道 */
    gst_bin_add_many(GST_BIN(pipeline), source, filter, convert, encoder, payloader, sink, NULL);

    /* 连接元素 */
    gst_element_link_many(source, filter, convert, encoder, payloader, sink, NULL);

    /* 开始播放 */
    gst_element_set_state(pipeline, GST_STATE_PLAYING);

    /* 消息循环 */
    bus = gst_element_get_bus(pipeline);
    msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR);
    msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_EOS);

    /* 释放资源 */
    if (msg != NULL)
        gst_message_unref(msg);

    /* 清理 */
    gst_object_unref(bus);
    gst_element_set_state(pipeline, GST_STATE_NULL);
    gst_object_unref(pipeline);

    return 0;
}